<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #box {
            background: orange;
            width: 200px;
            height: 200px;
            position: relative;
            margin: 120px auto;
        }

        #rotate {
            position: absolute;
            left: calc(50% - 10px);
            top: -40px;
            z-index: 99;
            background-color: pink;
            border: 1px solid red;
            display: block;
            width: 20px;
            height: 20px;
            cursor: move;
            user-select: none;
        }
    </style>
</head>

<body>
    <div id="box">
        <span id="rotate" title="旋转">转</span>
    </div>
    <script>
        var binder = document.querySelector("#rotate");
        var target = document.querySelector("#box");
        let startPoint = binder.getBoundingClientRect(binder);//夹脚开始位置
        let targetPoint = target.getBoundingClientRect(target);
        //三角函数的角度起点位置
        let origin = {
            x: targetPoint.x + targetPoint.width / 2,
            y: targetPoint.y + targetPoint.height / 2,
        }
        //第一次鼠标按下的位置
        let startData = {
            x: 0,
            y: 0
        };
        let prevAngle = 0;
        // 计算旋转角度
        function computedAngle(a, b, tab) {
            const x = a.x - b.x
            const y = a.y - b.y;
            let result = 180 * Math.atan2(y, x) / Math.PI;
            return result;
        }
        const mousemove = (e) => {
            const { pageX, pageY } = e;
            const durx = pageX - targetPoint.width / 2;
            const dury = pageY - targetPoint.height / 2;
            let angleCurrent = computedAngle(origin, { x: e.clientX, y: e.clientY });
            let angleStart = computedAngle(origin, startData, "start");
            let angle = angleCurrent - angleStart;
            let realAngle = angle += prevAngle;
            target.style.transform = `rotate(${realAngle}deg)`;
        }
        const mouseup = () => {
            document.removeEventListener("mousemove", mousemove)
            document.removeEventListener("mouseup", mouseup)
        }
        binder.addEventListener("mousedown", function (e) {
            //获取一设置的角度
            let arr = /rotate\((\d+(\.?)\d+)deg/.exec(target.style.transform)
            if (arr && arr[1]) {
                prevAngle = Number(arr[1]);
            }

            startData = {
                x: e.clientX,
                y: e.clientY
            }
            document.addEventListener("mousemove", mousemove)
            document.addEventListener("mouseup", mouseup)
        })

    </script>
</body>

</html>